﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;

namespace Rushabh.Xna.Framework
{
        public class Rectangle : IEquatable<Rectangle>
        {
            public int x, y, width, height;

            public int Bottom { get { return y + height; } }

            public int Top { get { return y; } }

            public int Right { get { return x + width; } }

            public int Left { get { return x; } }

            public Point Center
            {
                get
                {
                    Point p = new Point();
                    p.X = this.x + this.width / 2;
                    p.Y = this.y + this.height / 2;
                    return p;
                }
            }

            public Rectangle()
            {
                x = 0; y = 0; width = 0; height = 0;
            }

            public static Rectangle Empty { get { return new Rectangle(); } }            


            public Rectangle(int x, int y, int width, int height)
            {
                this.x = x;
                this.y = y;
                this.width = width;
                this.height = height;
            }

            public bool Contains(Point p)
            {
                if (p.X >= this.x && p.X <= this.x + this.width)
                    if (p.Y <= this.y + this.height && p.Y >= this.y)
                        return true;
                 
                        return false;
            }

            public bool Contains(Rectangle rect)
            {
                if (this.Contains(rect.Center)) 
                    return true;
                return false;
            }

            public override bool Equals(object obj)
            {
                return base.Equals(obj);
            }

            public bool Equals(Rectangle obj)
            {
                if(obj.x == this.x && obj.y == this.y && obj.height == this.height && obj.width == this.width)
                    return true;
                return false;
            }

            public bool Intersects(ref Rectangle rect)
            {
                if (this.Contains(new Point(rect.x, rect.y))
                    || this.Contains(new Point(rect.x + rect.width, rect.y))
                    || this.Contains(new Point(rect.x, rect.y + rect.height))
                    || this.Contains(new Point(rect.x + rect.width, rect.height + rect.y))
                    || rect.Contains(new Point(this.x, this.y))
                    || rect.Contains(new Point(this.x + this.width, this.y))
                    || rect.Contains(new Point(this.x, this.y + this.height))
                    || rect.Contains(new Point(this.x + this.width, this.y + this.height)))
                    return true;
                else
                    return false;
            }
        }

        public class Texture2D : Texture
        {
            public BitmapImage pixelTexture { get { return _texture; } set { _texture = value; } }

            public Rectangle Bounds { get { return _bounds; } set { _bounds = value; } }

            public String Name = String.Empty;

            private Texture2D()
            {
                _bounds = new Rectangle();
            }

            async public static Task<Texture2D> LoadComponent(Uri Path, String NameOfTexture)
            {
                BitmapImage img = new BitmapImage(Path) { CreateOptions = BitmapCreateOptions.None };
                Rectangle _bounds = new Rectangle(0, 0, img.PixelWidth, img.PixelHeight);
                Texture2D t = new Texture2D() { pixelTexture = img, Bounds = _bounds, Name = NameOfTexture };
                return t;
            }
        }

        public abstract class Texture : IDisposable
        {
            protected BitmapImage _texture;
            protected Rectangle _bounds;
            public Texture()
            {
                _texture = new BitmapImage();
                _bounds = new Rectangle();
            }

            public void Dispose() {
                _texture = null;
                _bounds = null;                
            }
        }     

        public interface IGame
        {
            void Initialize();
            void LoadComponent();
            void Update();
            void Draw();
        }

        public class GameTime : DispatcherTimer
        {
            private long ms, s, m, h, d, Ticks;
            static private TimeSpan currentTime = new TimeSpan();
            public EventHandler Render;
            public GameTime()
            {
                ms = s = m = d = h = Ticks = 0;
            }


            public void GameTimeUpdate()
            {
                ms += TimeSpan.TicksPerMillisecond * 66;
                currentTime.Add(new TimeSpan(0, 0, 0, 0, 66));
            }

            public void GameTimeUpdate(long ticks)
            {
                ms += TimeSpan.TicksPerMillisecond * ticks;
                currentTime.Add(new TimeSpan(ticks));
            }

            public TimeSpan GetTime()
            {
                return currentTime;
            }


        }

        public class SpriteBatch
        {
            Canvas canvas = new Canvas();
            Windows.UI.Core.CoreDispatcher Dispatcher;
            public SpriteBatch(Canvas canvas, Windows.UI.Core.CoreDispatcher currentDispatcher)
            { 
                this.canvas = canvas;
                this.Dispatcher = currentDispatcher;
            }

            async public void Draw(Texture2D texture, Rectangle rectange, Color Color)
            {
                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, new Windows.UI.Core.DispatchedHandler(() => {
                    Image img = new Image();
                    img.Height = rectange.height;
                    img.Width = rectange.width;
                    img.Name = texture.Name;
                    img.RenderTransform = new CompositeTransform() { TranslateX = rectange.x, TranslateY = rectange.y };
                    img.Source = texture.pixelTexture; 
                    canvas.Children.Add(img);
                }));
            }

            async public void Draw(Texture2D texture, Vector2 position, Color Color)
            {
                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, new Windows.UI.Core.DispatchedHandler(() =>
                {
                    Image img = new Image();
                    img.Name = texture.Name;
                    img.RenderTransform = new CompositeTransform() { TranslateX = position.x, TranslateY = position.y };
                    img.Source = texture.pixelTexture;
                    Border b = new Border();
                    b.Background.Opacity = 0.5;
                    b.BorderBrush = new SolidColorBrush() { Color = Color };
                    b.BorderThickness = new Thickness(0);
                    b.Child = img;
                    
                    
                    canvas.Children.Add(b);
                }));
            }

            async public void Draw(Texture2D texture, Vector2 position, Vector2 rotationCentre, float Rotation, Color Color)
            {
                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, new Windows.UI.Core.DispatchedHandler(() =>
                {
                    Image img = new Image();
                    img.Name = texture.Name;
                    img.RenderTransform = new CompositeTransform() { TranslateX = position.x, TranslateY = position.y, Rotation = Rotation, CenterX = rotationCentre.x, CenterY = rotationCentre.y };
                    img.Source = texture.pixelTexture;
                    Border b = new Border();
                    b.Background.Opacity = 0.5;
                    b.BorderBrush = new SolidColorBrush() { Color = Color };
                    b.BorderThickness = new Thickness(0);
                    b.Child = img;


                    canvas.Children.Add(b);
                    
                }));            
            }
        }

        public class GraphicsDevice
        {
            private static Canvas canvas;
            
            public static void setCanvas(Canvas _canvas)
            {
                canvas = _canvas;
            }

            public static void Clear(Color color)
            {
                canvas.Background = new SolidColorBrush() { Color = color };
                canvas.Children.Clear();
            }
        }

        public class Vector2
        {
            public float x, y;

            public static Vector2 Zero { get { return new Vector2() { x = 0, y = 0 }; } }

            public Point currentLocation { get { return new Point() { X = (int)x, Y = (int)y }; } }

            public static Vector2 One { get { return new Vector2() { x = 1f, y = 1f }; } }

            public Vector2()
            {
                x = 0; y = 0;
            }

            public Vector2(float x, float y)
            {
                this.x = x;
                this.y = y;
            }

            public static Vector2 Add(Vector2 vector1, Vector2 vector2)
            {
                return new Vector2(vector1.x + vector2.x, vector1.y + vector2.y);
            }

            public static double Distance(Vector2 vector1, Vector2 vector2)
            {
                return Math.Sqrt(Math.Pow((double)vector1.x - (double)vector2.x, (double)2) + Math.Pow((double)vector1.y - (double)vector2.y, (double)2));
            }
        }
}
